package thread.waitnotifypackage;

import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 自己实现的生产者/消费者模式，但是无法保证生产一个立刻就消费一个这种顺序（即ABCABCABC这种顺序），
 */
public class CustomCP {

    private static final LinkedList<Integer> queue = new LinkedList();

    static Thread consumer = new Thread() {
        @Override
        public void run() {
            while (true) {
                synchronized (queue) {
                    System.out.println("consumer 当前队列为：" + queue.toString());
                    while (queue.size() == 0) {
                        try {
                            System.out.println("消费锁住了");
                            queue.wait(); // 释放锁 在这停住
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("取出值为：" + queue.poll());
                    queue.notifyAll(); // 释放锁，并通知所有锁池里的线程去获取锁
                }
            }
        }
    };

    static Thread producer = new Thread() {
        @Override
        public void run() {
            while (true) {
                synchronized (queue) {
                    System.out.println("producer 当前队列为：" + queue.toString());
                    while (queue.size() >= 5) {
                        try {
                            System.out.println("生产锁住了");
                            queue.wait();// 释放锁 在这停住! 5个之前没有调wait 所以会一直加到5个元素 再wait 进而再消费
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    Integer a = new Random().nextInt(9);
                    System.out.println("插入值为：" + a);
                    queue.offer(a);
                    queue.notifyAll(); // 释放锁，并通知所有锁池里的线程去获取锁
                }
            }
        }
    };

    public static void main(String[] args) {
        ExecutorService threadPool = new ThreadPoolExecutor(20, 20,
            0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

        for (int i = 0; i < 5; i++) {
            threadPool.execute(consumer);
            threadPool.execute(producer);
        }
    }

}
